package edu.ujf.sharepas.impl;
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import edu.ujf.sharepas.rmi.Client;
import edu.ujf.sharepas.rmi.Serveur;

import util.*;

public class ServeurImpl extends UnicastRemoteObject implements Serveur {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2748283870135907373L;
	private Map<String, Client> connectedUsers ;
	private Fenetre f;
	private static String url;


	// Constructeur
	public ServeurImpl() throws RemoteException{
		super();
		connectedUsers = new HashMap<String, Client>();
		f=new Fenetre();
		f.setVisible(true);
		f.ajoutTexte("> Serveur : pret\n");
	}


	// Programme principal  
	public static void main (String args[]) throws Exception {


		ServeurImpl leServeur = new ServeurImpl();
		url = Constante.getSharePasProperty(Constante.Property.SERV_NAME.toString());
		String listenAddr = Constante.getSharePasProperty(Constante.Property.SERVER_ADDR.toString());
		Registry reg =null;
		try{
			reg = LocateRegistry.createRegistry(1099);
		}catch(Exception e){
			reg = LocateRegistry.getRegistry(listenAddr);	
		}	
		reg.rebind(url,leServeur);
	}


	public void connect(Client client) throws RemoteException {

		User user = client.getUser();
		if(connectedUsers.get(user.getName()) == null){
			connectedUsers.put(user.getName(), client);
			updateUsers();
			f.ajoutTexte(user.getName()+" is connected\n");
		}

	}

	public void updateUser(Client u) throws RemoteException{
		try {
			connectedUsers.put(u.getUser().getName(), u);
			updateUsers();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void updateUsers() {
		Set<Entry<String, Client>> users = connectedUsers.entrySet() ;
		List<User> listUser = new ArrayList<User>();
		
		for (Entry<String, Client> e : users ){
			try{
				listUser.add(e.getValue().getUser());
				f.ajoutTexte("user "+e.getValue().getUser().getName()+" state "+e.getValue().getUser().getState());
				if( e.getValue().getUser().getFriends() != null ){
					for(User u:e.getValue().getUser().getFriends()){
						if( !listUser.contains(u) ){
							f.ajoutTexte("user "+u.getName()+" state "+u.getState());
							listUser.add(u);
						}
					}
				}
			} catch (RemoteException e1) {
				e1.printStackTrace();
			}
		}
		// send user list to all client
		for( Entry<String,Client> e:users){
			try{
				e.getValue().updateFriends(listUser);
				f.ajoutTexte("send to client "+e.getValue().getUser().getName());
			}catch(RemoteException e1) {
				e1.printStackTrace();
			}
		}
	}


	public void disconnect(Client client) throws RemoteException {

		User user = client.getUser();
		if(connectedUsers.get(user.getName()) != null){
			connectedUsers.remove(user.getName());
			//message(new Message(user+" is disconnected"));
			f.ajoutTexte(user.getName()+" is disconnected\n");
		}

	}

	public void message(Message m) throws RemoteException {

		Set<java.util.Map.Entry<String, Client>> users = connectedUsers.entrySet();
		for(Entry<String, Client> user : users){
			Client clientObject = user.getValue();
			if (clientObject != null){
				clientObject.send(m);
			}else{
				disconnect(clientObject);
			}

		}
		

	}


	public String getUrl() throws RemoteException {
		return url;
	}




}
